// 封装axios的请求，返回重新封装的数据格式
// 对错误的统一处理
import axios from 'axios'
import errorHandle from './errorHandle'
import { TOKEN } from '@/constant'

class HttpRequest {
  baseUrl: string
  pending: any

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl
    this.pending = {}
  }

  getBaseUrl() {
    return this.baseUrl
  }

  // 获取axios配置
  getInsideConfig() {
    const config = {
      baseURL: this.baseUrl,
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
      },
      timeout: 30000,
    }
    return config
  }

  removePending(key: any, isRequest = false) {
    if (this.pending[key] && isRequest) {
      this.pending[key]('取消重复请求')
    }
    delete this.pending[key]
  }

  // 设定拦截器
  interceptors(instance: any) {
    // 请求拦截器
    instance.interceptors.request.use(
      (config: any) => {
        const token = localStorage.getItem(TOKEN)
        if (token) {
          config.headers.token = token
        }
        return config
      },
      (err: any) => {
        errorHandle(err, null)
        return Promise.reject(err)
      },
    )

    // 响应请求的拦截器
    instance.interceptors.response.use(
      (res: any) => {
        const key = res.config.url + '&' + res.config.method
        this.removePending(key)
        if (res.status === 200) {
          if (res.data.code === 200) {
            return Promise.resolve(res.data.data)
          } else if (res.data.code === 600) {
            return Promise.resolve(res.data)
          } else {
            if (res.config.responseType === 'blob') {
              return Promise.resolve({
                data: res.data,
                filename: decodeURI(res.headers['content-disposition']),
              })
            }
            errorHandle(res, null)
            return Promise.reject(res)
          }
        } else {
          errorHandle(res, null)
          return Promise.reject(res)
        }
      },
      (err: any) => {
        errorHandle(null, err)
        return Promise.reject(err)
      },
    )
  }

  // 创建实例
  request(options: any) {
    options = options || {}
    const instance = axios.create()
    const newOptions = Object.assign(this.getInsideConfig(), options)
    this.interceptors(instance)
    return instance(newOptions)
  }

  get(url: string, params: any, extra: Record<string, any> | null = null) {
    const options = Object.assign({
      method: 'get',
      url,
      params,
    })
    if (extra) {
      Object.keys(extra).map((key: string) => {
        options[key] = extra[key]
      })
    }
    return this.request(options)
  }

  post(url: string, data: any, extra: Record<string, any> | null = null) {
    const options: any = {
      method: 'post',
      url,
      data,
    }
    if (extra) {
      Object.keys(extra).map((key: string) => {
        options[key] = extra[key]
      })
    }
    return this.request(options)
  }

  upload(url: string, data: any, extra: Record<string, any> | null = null) {
    const formData = new FormData()
    if (Array.isArray(data)) {
      for (const file of data) {
        formData.append('files', file)
      }
    } else {
      formData.append('files', data)
    }
    if (extra) {
      Object.keys(extra).map((key: string) => {
        formData.append(key, extra[key])
      })
    }
    return this.request({
      method: 'post',
      url,
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      timeout: 180000,
    })
  }
}

export default HttpRequest
